﻿using CommData;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace CommHelper
{
    public class NetworkDataHelper
    {

        private static NetworkDataHelper m_NetworkDataHelper = null;
        /// <summary>
        /// 自定义网络协议帮助
        /// </summary>
        public static NetworkDataHelper GetNetworkDataHelper
        {
            get
            {
                if (m_NetworkDataHelper == null)
                {
                    m_NetworkDataHelper = new NetworkDataHelper();
                }
                return m_NetworkDataHelper;
            }
        }

        public int DataHeaderLength
        {
            get
            {
                return m_dataIndex;
            }
        }

        public int GetDateLength(byte[] value)
        {
            return BitConverter.ToInt32(value, m_lenIndex);
        }

        public int GetErrorCode(byte[] value)
        {
            return BitConverter.ToInt32(value, m_errCodeIndex);
        }

        public string GetMethod(byte[] value)
        {
            return System.Text.Encoding.UTF8.GetString(value, m_methodIndex, 32);
        }

        private readonly int m_magicIndex = 0;
        private readonly int m_verIndex = 2;
        private readonly int m_lenIndex = 4;
        private readonly int m_errCodeIndex = 8;
        private readonly int m_ipIndex = 12;
        private readonly int m_methodIndex = 16;
        private readonly int m_dataIndex = 48;


        /// <summary>
        /// 将对象转为 json 字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public string GetJsonString<T>(T t)
        {
            System.Web.Script.Serialization.JavaScriptSerializer javaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer() { MaxJsonLength = int.MaxValue };
            return javaScriptSerializer.Serialize(t);
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="input"></param>
        /// <returns></returns>
        public T DeserializeJson<T>(string input)
        {
            System.Web.Script.Serialization.JavaScriptSerializer javaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer() { MaxJsonLength = int.MaxValue };
            return javaScriptSerializer.Deserialize<T>(input);
        }

        /// <summary>
        /// 对象转为json流
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public byte[] GetJsonBytes<T>(T t)
        {
            string jsontext = GetJsonString<T>(t);
            jsontext = DESEncryptHelper.Encrypt(jsontext);
            return Encoding.UTF8.GetBytes(jsontext);
        }

        /// <summary>
        /// 封装请求流
        /// </summary>
        /// <param name="method"></param>
        /// <param name="ResponseBody"></param>
        /// <returns></returns>
        public byte[] GetRequestBytes<T>(string method,T t)
        {
            return GetRequestBytes( method, t,  NetHelper.Iptoint);
        }

        /// <summary>
        /// 封装请求流
        /// </summary>
        /// <param name="method"></param>
        /// <param name="ResponseBody"></param>
        /// <returns></returns>
        public byte[] GetRequestBytes<T>(string method, T t, uint ipaddress, short ver = 1)
        {
            Debug.Assert(method.Length <= 32);

            List<byte> bytelist = new List<byte>();
            bytelist.AddRange(new byte[2]);
            bytelist.AddRange(new byte[2]);
            bytelist.AddRange(new byte[4]);
            bytelist.AddRange(new byte[4]);//添加ip
            bytelist.AddRange(new byte[4]);
            bytelist.AddRange(new byte[32]);
            var responseBody = (null == t) ? null : GetJsonBytes<T>(t);
            if (responseBody != null)
            {
                bytelist.AddRange(responseBody);
            }
            var bytes = bytelist.ToArray();
            BitConverter.GetBytes(ConstData.MAGIC).CopyTo(bytes, m_magicIndex);
            BitConverter.GetBytes(ver).CopyTo(bytes, m_verIndex);
            BitConverter.GetBytes(null == t ? 0 : responseBody.Length).CopyTo(bytes, m_lenIndex);
            BitConverter.GetBytes(-1).CopyTo(bytes, m_errCodeIndex);
            BitConverter.GetBytes(ipaddress).CopyTo(bytes, m_ipIndex);//添加ip
            System.Text.Encoding.UTF8.GetBytes(method).CopyTo(bytes, m_methodIndex);
            return bytes;
        }

        /// <summary>
        /// 封装返回流
        /// </summary>
        /// <param name="method"></param>
        /// <param name="ResponseBody"></param>
        /// <returns></returns>
        public byte[] GetResponseBytes<T>(MessageStatus retrunCode, string method, T t,uint ipaddress ,short ver = 1)
        {
            Debug.Assert(method.Length <= 32);

            List<byte> bytelist = new List<byte>();
            bytelist.AddRange(new byte[2]);
            bytelist.AddRange(new byte[2]);
            bytelist.AddRange(new byte[4]);
            bytelist.AddRange(new byte[4]);//添加ip
            bytelist.AddRange(new byte[4]);
            bytelist.AddRange(new byte[32]);
            var responseBody = (null == t) ? null : GetJsonBytes<T>(t);
            if (responseBody != null)
            {
                bytelist.AddRange(responseBody);
            }
            var bytes = bytelist.ToArray();
            BitConverter.GetBytes(ConstData.MAGIC).CopyTo(bytes, m_magicIndex);
            BitConverter.GetBytes(ver).CopyTo(bytes, m_verIndex);
            BitConverter.GetBytes(null == t ? 0 : responseBody.Length).CopyTo(bytes, m_lenIndex);
            BitConverter.GetBytes((int)retrunCode).CopyTo(bytes, m_errCodeIndex);
            BitConverter.GetBytes(ipaddress).CopyTo(bytes, m_ipIndex);//添加ip
            System.Text.Encoding.UTF8.GetBytes(method).CopyTo(bytes, m_methodIndex);

            return bytes;
        }

        /// <summary>
        /// 返回错误码
        /// </summary>
        /// <param name="errCode"></param>
        /// <param name="method"></param>
        /// <param name="ver"></param>
        /// <returns></returns>
        public byte[] ResponseErrorCode(MessageStatus errCode, string method,uint ipaddress, short ver = 1)
        {
            return GetResponseBytes<object>(errCode, method, null, ipaddress, ver);
        }

        /// <summary>
        /// 返回异常信息
        /// </summary>
        /// <param name="e"></param>
        /// <param name="method"></param>
        /// <param name="ver"></param>
        /// <returns></returns>
        public byte[] ResponseException(Exception e, string method, uint ipaddress, short ver = 1)
        {
            Dictionary<string, object> ex = new Dictionary<string, object>();
            ex.Add("exception", e.Message);

            return GetResponseBytes(MessageStatus.Exception, method, ex, ipaddress, ver);
        }

       

        /// <summary>
        /// 返回对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="contenttype"></param>
        /// <param name="contentdata"></param>
        /// <returns></returns>
        public T GetJsonObject<T>(byte[] contentdata)
        {
            T t = default(T);
            System.Web.Script.Serialization.JavaScriptSerializer serialization = new System.Web.Script.Serialization.JavaScriptSerializer() { MaxJsonLength = int.MaxValue };
            var jsonstr = Encoding.UTF8.GetString(contentdata);
            t = serialization.Deserialize<T>(DESEncryptHelper.Decrypt(jsonstr));
            return t;
        }

        /// <summary>
        /// 返回对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="contenttype"></param>
        /// <param name="contentdata"></param>
        /// <returns></returns>
        public T GetJsonObject<T>(string contentdata)
        {
            T t = default(T);
            System.Web.Script.Serialization.JavaScriptSerializer serialization = new System.Web.Script.Serialization.JavaScriptSerializer() { MaxJsonLength = int.MaxValue };
            t = serialization.Deserialize<T>(DESEncryptHelper.Decrypt(contentdata));
            return t;
        }

        /// <summary>
        /// 验证数据是否正确
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="requestlength"></param>
        /// <param name="requestBytes"></param>
        /// <param name="methodName"></param>
        /// <returns></returns>
        public MessageStatus CheckData(byte[] bytes, ref int requestlength, ref byte[] requestBytes,
            ref string methodName, ref int errCode,ref uint ipaddress)
        {
            MessageStatus messageStatus = MessageStatus.Success;
            try
            {
                if (requestlength < 0)
                {
                    if (bytes.Length >= DataHeaderLength)
                    {
                        if (ConstData.MAGIC != BitConverter.ToInt16(bytes, m_magicIndex))
                        {
                            throw new Exception("Invalid magic header!");
                        }
                        requestlength = BitConverter.ToInt32(bytes, m_lenIndex);
                        methodName = System.Text.Encoding.UTF8.GetString(bytes, m_methodIndex, 32);
                        methodName = methodName.TrimEnd('\0');
                        errCode = GetErrorCode(bytes);
                        ipaddress = BitConverter.ToUInt32(bytes, m_ipIndex);
                    }
                    else
                    {
                        return MessageStatus.Packet_Length_Error;
                    }
                }
                if (bytes.Length >= requestlength + DataHeaderLength)
                {
                    requestBytes = new byte[requestlength];
                    bytes.ToList().CopyTo(m_dataIndex, requestBytes, 0, requestBytes.Length);
                    messageStatus = MessageStatus.Success;
                }
                else
                {
                    messageStatus = MessageStatus.Packet_Length_Error;
                }
            }
            catch (Exception e)
            {
                LogHelper.WriteErrorLog(e.Message);
                messageStatus = MessageStatus.Analysis_Error;
            }
            return messageStatus;
        }

        /// <summary>
        /// 返回方法的Respons请求流
        /// 所给参数的顺序必须和原方法的参数顺序一致
        /// </summary>
        /// <param name="paramgers">方法的参数</param>
        /// <returns></returns>
        public byte[] GetFunctionResponsBytes(params  object[] paramgers)
        {
            byte[] responsBytes = null;
            var method = new System.Diagnostics.StackFrame(1).GetMethod();
            var methodParamgers = method.GetParameters();
            if (paramgers.Length != methodParamgers.Length)
            {
                CommHelper.LogHelper.WriteErrorLog("方法参数数量与传递的参数个数不一致，获取方法的Respons流失败！");
                return responsBytes;
            }
            Dictionary<string, object> dicPara = new Dictionary<string, object>();
            for (int index = 0; index < paramgers.Length; index++)
            {
                dicPara.Add(methodParamgers[index].Name, paramgers[index]);
            }
            responsBytes = GetNetworkDataHelper.GetRequestBytes(method.Name, dicPara);
            return responsBytes;
        }

        /// <summary>
        /// 将json数据反序列化为Dictionary
        /// </summary>
        /// <param name="jsonData">json数据</param>
        /// <returns></returns>
        public Dictionary<string, object> JsonToDictionary(string jsonData)
        {
            //实例化JavaScriptSerializer类的新实例
            System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer() { MaxJsonLength = int.MaxValue };
            try
            {
                //将指定的 JSON 字符串转换为 Dictionary<string, object> 类型的对象
                return jss.Deserialize<Dictionary<string, object>>(jsonData);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
    }
}
